#pragma once

#include <map>
#include <memory>
#include <string>
#include <vector>
#include "../GrpcModule/GrpcModule.grpc.pb.h"
#include "../Config/ImportDataConfig.h"
#include "../Base/CriticalSection.h"
#include "ImportDataThread.h"
#include "EnclaveProvider.h"
#include "Config.h"
#include "ImportDataCache.h"
#include "../DataModule/HanaData.h"
#include "../DataModule/MysqlData.h"

class ImportDataThread;

class ImportData
{
public:
    ImportData(std::shared_ptr<EnclaveProvider> enclave_provider, Config &config);
    ~ImportData();

    void importData(const ::enclave::ImportDataRequest* request, ::grpc::ServerWriter< ::enclave::ImportDataResponse>* writer);

    bool getTableFields(TableConfig **table_config, std::vector<Field> **columns, std::vector<Field> &selected_columns, IData::Fields &fields, int &rows_num, ImportDataCache::Data &pos);

	void importProgress(ImportDataThread *thread, TableConfig& table_config, int length);

	void removeFaild(const char *table, ImportDataCache::Data &data);

private:
	void addFaild(const char *table, ImportDataCache::Data &data);

public:
    static std::vector<Field> columns_ex_;

private:
    Config config_;

    ImportDataConfig import_data_config_;

    int table_index_ = 0;

	std::map<std::string, ImportDataCache::Data> tables_pos_;

    std::map<std::string, int> tables_count_;
    std::map<std::string, int> tables_imported_count_;
    std::map<std::string, std::vector<Field>> tables_columns_;

    std::vector<std::shared_ptr<ImportDataThread>> import_threads_;

    ::grpc::ServerWriter<::enclave::ImportDataResponse>* writer_;

	std::shared_ptr<EnclaveProvider> enclave_provider_;

	ImportDataCache import_data_cache_;

    CriticalSection critical_section_;

    CriticalSection imported_count_cs_;

    std::map<std::string, std::vector<ImportDataCache::Data>> faild_cache_datas_;
    std::map<std::string, ImportDataCache::Data> success_cache_pos_;

	MysqlData *data_src_ = nullptr;
	HanaData *data_des_ = nullptr;
};

